package com.interview.a_多线程.e_Thread和Object中的重要方.d_wai_notify_生产消费模型;

import java.util.LinkedList;

/**
 * 通过 wait 和 notify
 * 并且不使用 阻塞队列的情况下
 * 实现生产者消费者模型
 */
public class ProducerAndConsumer {
    public static void main(String[] args) throws InterruptedException {
        Warehouse warehouse = new Warehouse();

        Producer producer = new Producer(warehouse);
        Thread thread1 = new Thread(producer);
        thread1.start();


        Consumer consumer = new Consumer(warehouse);
        Thread thread2 = new Thread(consumer);
        thread2.start();
        Thread.sleep(5000);
    }


}

class Warehouse {
    public int max;
    public LinkedList<String> storage;

    public Warehouse() {
        this.max = 10;
        this.storage = new LinkedList<>();
    }

    //    生产
    public synchronized void add(String content) {
        //
        if (storage.size() == max) {
            try {
                System.out.println("生产数量达到最大值，进行等待....");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        storage.add(content);
        notify();
        System.out.println("生产 : " + content);
    }

    //    消费
    public synchronized void task() {

        if (storage.size() == 0) {
            try {
                System.out.println("全部消费完成，进行等待....");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("消费：" + storage.poll() + "  剩余：" + storage.size());
        notify();
    }
}

class Producer implements Runnable {
    private Warehouse warehouse;

    Producer(Warehouse warehouse) {
        this.warehouse = warehouse;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            warehouse.add(i + "");
        }
    }
}

class Consumer implements Runnable {
    private Warehouse warehouse;

    Consumer(Warehouse warehouse) {
        this.warehouse = warehouse;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            warehouse.task();
        }
    }
}